package com.ziyucoding.springboot.labs.statemachine.aop;

import com.ziyucoding.springboot.labs.statemachine.annotation.OrderStateMachineResult;
import com.ziyucoding.springboot.labs.statemachine.common.CommonConstants;
import com.ziyucoding.springboot.labs.statemachine.common.OrderStatus;
import com.ziyucoding.springboot.labs.statemachine.common.OrderStatusChangeEvent;
import com.ziyucoding.springboot.labs.statemachine.domain.Order;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.messaging.Message;
import org.springframework.statemachine.StateMachine;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;

/**
 * 订单状态机结果切面
 *
 * @author ziyucoding
 * @date 2023-05-29
 **/
@Component
@Aspect
@Slf4j
public class OrderStateMachineResultAspect {

    @Resource
    private StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;

    /**
     * 拦截 OrderStateMachineResult 注解
     *
     * @return void
     */
    @Pointcut("@annotation(com.ziyucoding.springboot.labs.statemachine.annotation.OrderStateMachineResult)")
    private void orderStateMachineResultPointCut() {
        // orderStateMachineResultPointCut 注解切点
    }

    @Around("orderStateMachineResultPointCut()")
    public Object orderStateMachineResultAround(ProceedingJoinPoint pjp) throws Throwable {
        // 获取参数
        Object[] args = pjp.getArgs();
        log.info("参数args:{}", args);
        Message message = (Message) args[0];
        Order order = (Order) message.getHeaders().get("order");
        // 获取方法
        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
        // 获取LogHistory注解
        OrderStateMachineResult result = method.getAnnotation(OrderStateMachineResult.class);
        String key = result.key();
        String orderKeyVar = key + order.getId();
        Object returnVal = null;
        try {
            // 执行方法
            returnVal = pjp.proceed();
            // 如果业务执行正常，则保存信息
            // 成功 则为1
            orderStateMachine.getExtendedState().getVariables().put(orderKeyVar, CommonConstants.SUCCESS);
        } catch (Throwable e) {
            log.error("OrderStateMachineResultAspect::orderStateMachineResultAround 发生异常", e);
            // 如果业务执行异常，则保存信息
            // 将异常信息变量信息中，失败则为0
            orderStateMachine.getExtendedState().getVariables().put(orderKeyVar, CommonConstants.FAILED);
            throw e;
        }
        return returnVal;
    }
}
